#include <linkedlist.h>
#include <coord.h>
#include <unittest.h>

/**
 * DESC: Tests linked list implementation.
 *
 * IMP: HIGH
 */

struct rect_node {
  listnode_t node;
  coord_t pos;
};

int rect_node_cmp( const listnode_t *a, const listnode_t *b )
{
  struct rect_node *i, *j;
  int r;

  i = (struct rect_node *)a;
  j = (struct rect_node *)b;


  if ( i->pos.x < j->pos.x )
    r = -1;
  else if ( i->pos.x == j->pos.x )
    r = 0;
  else
    r = 1;

  return r;
}


int main( int argc, char *argv[] )
{
  linkedlist_t *l = list_new();
  struct rect_node *node;

  assert_not_null( l );

  int i;
  for ( i=0; i < 10; i++ )
    {
      node = list_add( l, typeof(*node) );
      SET_COORD( node->pos, i, 0 );
      printf( "\t %p <- %p -> %p\n",
	       LIST_PREV(node), node, LIST_NEXT(node) );
    }

  fprintf( stderr, "print list:\n" );
  int j = 0;
  for_each_list_element( l, node )
    {
      printf( "%p ( %d, %d )\n", node, node->pos.x, node->pos.y );
      j++;
    }
  assert_equal_int( i, j );

  printf( "delete the last element:\n" );
  list_del( l, LIST_PREV(node) );

  printf( "print list:\n" );
  j = 0;
  for_each_list_element( l, node )
    {
      printf( "%p ( %d, %d )\n", node, node->pos.x, node->pos.y );
      j++;
    }
  assert_equal_int( i, j + 1 );

  printf( "delete the first element:\n" );
  list_del( l, l->node->next );

  printf( "print list:\n" );
  j = 0;
  for_each_list_element( l, node )
    {
      printf( "%p ( %d, %d )\n", node, node->pos.x, node->pos.y );
      j++;
    }
  assert_equal_int( i, j + 2 );

  list_clear( l );

  struct rect_node n;

  printf( "Insert in order with a clean list:\n" );

  for ( i=10; i > 0; i-- )
    {
      SET_COORD( n.pos, i, 0 );
      node = list_insert_in_order( l, n, rect_node_cmp );
      printf( "\t insert_in_order( %d, %d ) %p <- %p -> %p\n",
	      n.pos.x, n.pos.y, LIST_PREV(node), node, LIST_NEXT(node) );
    }
  printf( "print list:\n" );
  j = 0;
  for_each_list_element( l, node )
    {
      printf( "%p ( %d, %d )\n", node, node->pos.x, node->pos.y );
      j++;
    }
  assert_equal_int( j, 10 );

  printf( "Insert in order with a non-empty list:\n" );

  for ( i=10; i > 0; i-- )
    {
      SET_COORD( n.pos, i, 0 );
      node = list_insert_in_order( l, n, rect_node_cmp );
      printf( "\t insert_in_order( %d, %d ) %p <- %p -> %p\n",
	      n.pos.x, n.pos.y, LIST_PREV(node), node, LIST_NEXT(node) );
    }
  printf( "print list:\n" );
  j = 0;
  for_each_list_element( l, node )
    {
      printf( "%p ( %d, %d )\n", node, node->pos.x, node->pos.y );
      j++;
    }
  assert_equal_int( j, 20 );


  list_free( l );

  return 0;
}
